using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace WebTools.UI.WebControls
{
	#region Xml Doc
	/// <summary>
	/// Provides a control for displaying alert messages such as validation errors, successful operation and warning messages.
	/// </summary>
	/// <remarks>
	/// <para>
	/// The Alert control can provide messages to web application users in the form of error or success messages. 
	/// Validation controls can be used to supply messages to the alert as well as setting the <b>ErrorText</b> 
	/// and <b>SuccessText</b> values.
	/// </para>
	/// </remarks>
	/// <example>
	/// <para>
	/// The following examples demonstrate the use of the Alert control to render validation warnings and display a success message 
	/// to the user.
	/// </para>
	/// <para>
	/// This example uses the ASP.NET <seealso cref="System.Web.UI.WebControls.Login"/> control and renders the 
	/// validation errors for the Login control to the Alert control.
	/// </para>
	/// <para>
	///	The following code sample is from an ASPX page that has referenced the WebTools.UI.WebControls.Alert control.
	/// </para>
	/// <para>
	/// <code>
	/// <![CDATA[
	///		<div>
	/// 		<webtools:alert id="Alert1" runat="server" ErrorImageUrl="~/images/error.gif" SuccessImageUrl="~/images/info.gif" AlertType="Success" ValidationGroup="Login1">
	/// 			<ErrorStyle BackColor="Salmon" BorderColor="DarkRed" BorderStyle="Solid" BorderWidth="1px"
	/// 				ForeColor="DarkRed" HorizontalAlign="NotSet" HorizontalPadding="4px" VerticalPadding="4px" />
	/// 			<SuccessStyle BackColor="LightGreen" BorderColor="DarkGreen" BorderStyle="Solid"
	/// 				BorderWidth="1px" ForeColor="DarkGreen" HorizontalPadding="4px" VerticalPadding="4px" HorizontalAlign="NotSet" />
	/// 			<ImagePanelStyle HorizontalAlign="Center" />
	/// 		</webtools:alert>
	/// 		
	/// 		<asp:Login ID="Login1" runat="server" OnAuthenticate="Login1_Authenticate" OnLoginError="Login1_LoginError">
	/// 			<LayoutTemplate>
	/// 				<table border="0" cellpadding="1" cellspacing="0" style="border-collapse: collapse">
	/// 					<tr>
	/// 						<td>
	/// 							<table border="0" cellpadding="0">
	/// 								<tr>
	/// 									<td align="center" colspan="2">
	/// 										Log In</td>
	/// 								</tr>
	/// 								<tr>
	/// 									<td align="right">
	/// 										<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">User Name:</asp:Label></td>
	/// 									<td>
	/// 										<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
	/// 										<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName"
	/// 											ErrorMessage="User Name is required." ToolTip="User Name is required." ValidationGroup="Login1">*</asp:RequiredFieldValidator>
	/// 									</td>
	/// 								</tr>
	/// 								<tr>
	/// 									<td align="right">
	/// 										<asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="Password">Password:</asp:Label></td>
	/// 									<td>
	/// 										<asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
	/// 										<asp:RequiredFieldValidator ID="PasswordRequired" runat="server" ControlToValidate="Password"
	/// 											ErrorMessage="Password is required." ToolTip="Password is required." ValidationGroup="Login1">*</asp:RequiredFieldValidator>
	/// 									</td>
	/// 								</tr>
	/// 								<tr>
	/// 									<td colspan="2">
	/// 										<asp:CheckBox ID="RememberMe" runat="server" Text="Remember me next time." />
	/// 									</td>
	/// 								</tr>
	/// 								<tr>
	/// 									<td align="right" colspan="2">
	/// 										<asp:Button ID="LoginButton" runat="server" CommandName="Login" Text="Log In" ValidationGroup="Login1" />
	/// 									</td>
	/// 								</tr>
	/// 							</table>
	/// 						</td>
	/// 					</tr>
	/// 				</table>
	/// 			</LayoutTemplate>
	/// 		</asp:Login>
	///    </div>
	/// ]]>
	/// </code>
	/// </para>
	/// <para>
	/// The following code sample contains the events for the ASP.NET controls in the ASPX sample above.
	/// </para>
	/// <para>
	/// <code>
	///	C#
	/// <![CDATA[
	/// protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
	/// {
	/// 	if (Login1.UserName.Equals("User") && Login1.Password.Equals("password"))
	/// 	{
	/// 		e.Authenticated = true;
	/// 	}
	/// }
	/// protected void Login1_LoginError(object sender, EventArgs e)
	/// {
	/// 	Alert1.ErrorText = Login1.FailureText;
	/// }
	/// ]]>
	/// </code>
	/// </para>
	/// <para>
	/// This example demonstrates the use of the Alert control to render a success message to the user.
	/// </para>
	/// <para>
	///	The following code sample is from an ASPX page that has referenced the WebTools.UI.WebControls.Alert control.
	/// </para>
	/// <para>
	/// <code>
	/// <![CDATA[
	///		<div>
	/// 		<webtools:alert id="Alert1" runat="server" ErrorImageUrl="~/images/error.gif" SuccessImageUrl="~/images/info.gif" AlertType="Success" ValidationGroup="Login1">
	/// 			<ErrorStyle BackColor="Salmon" BorderColor="DarkRed" BorderStyle="Solid" BorderWidth="1px"
	/// 				ForeColor="DarkRed" HorizontalAlign="NotSet" HorizontalPadding="4px" VerticalPadding="4px" />
	/// 			<SuccessStyle BackColor="LightGreen" BorderColor="DarkGreen" BorderStyle="Solid"
	/// 				BorderWidth="1px" ForeColor="DarkGreen" HorizontalPadding="4px" VerticalPadding="4px" HorizontalAlign="NotSet" />
	/// 			<ImagePanelStyle HorizontalAlign="Center" />
	/// 		</webtools:alert>
	/// 		<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
	/// 		<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Update" />
	/// 	</div>
	/// ]]>
	/// </code>
	/// </para>
	/// <para>
	/// The following code sample contains the events for the ASP.NET controls in the ASPX sample above.
	/// </para>
	/// <para>
	/// <code>
	/// C#
	/// <![CDATA[
	/// protected void Button1_Click(object sender, EventArgs e)
	/// {
	/// 	Alert1.HeaderText = "You entered the following text:";
	/// 	Alert1.SuccessText = TextBox1.Text;
	/// }
	/// ]]>
	/// </code>
	/// </para>
	/// </example>
	#endregion
	[ToolboxData(@"<{0}:Alert runat=""server""></{0}:Alert>")]
	[System.Drawing.ToolboxBitmap("WebTools.UI.WebControls.Alert.bmp")]
	[DefaultProperty("Text")]
	[ControlValueProperty("Text")]
	[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
	[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
	public class Alert : WebControl
	{
		#region Private Fields
		private AlertType _alertType = AlertType.Error;
		private List<string> _content = new List<string>();
		private AlertStyle _errorStyle;
		private AlertStyle _successStyle;
		private AlertStyle _imagePanelStyle;
		private AlertStyle _headerStyle;
		private string _text;
		#endregion

		#region Constructor
		/// <summary>
		/// Initializes a new instance of the WebTools.UI.WebControls.Alert class.
		/// </summary>
		public Alert()
		{
		}
		#endregion

		#region Overridden Methods
		/// <summary>
		/// Renders the control begin tag.
		/// </summary>
		/// <param name="writer">The HtmlTextWriter to write output to.</param>
		public override void RenderBeginTag(HtmlTextWriter writer)
		{
			switch (this.AlertType)
			{
				case AlertType.Error:
					this.ApplyStyle(this.ErrorStyle);
					break;
				case AlertType.Success:
					this.ApplyStyle(this.SuccessStyle);
					break;
			}
			// Force the width of the containing table to 100% if not set.
			if (this.ControlStyle.Width.IsEmpty)
			{
				this.ControlStyle.Width = Unit.Percentage(100);
			}
			base.RenderBeginTag(writer);
		}

		/// <summary>
		/// Causes the web server control to render to the specified HtmlTextWriter.
		/// </summary>
		/// <param name="writer">The HtmlTextWriter to write output to.</param>
		protected override void Render(HtmlTextWriter writer)
		{
			if (this.ContainsContent())
			{
				this.RenderBeginTag(writer);
				this.RenderContents(writer);
				this.RenderEndTag(writer);
			}
			else
			{
				if (this.DesignMode)
				{
					this.RenderDesignContents(writer);
				}
			}
		}

		/// <summary>
		/// Renders the contents of the current web server control.
		/// </summary>
		/// <param name="writer">The HtmlTextWriter to write output to.</param>
		protected override void RenderContents(HtmlTextWriter writer)
		{
			//====================================================================================
			// Left Image
			//====================================================================================
			string url = null;
			switch (this.AlertType)
			{
				case AlertType.Error:
					url = this.ErrorImageUrl;
					break;
				case AlertType.Success:
					url = this.SuccessImageUrl;
					break;
			}

			// Only one row in the table, contains two columns, one for the image and
			// the other for the text.
			writer.RenderBeginTag(HtmlTextWriterTag.Tr); // <tr>

			if (!String.IsNullOrEmpty(url))
			{
				this.ImagePanelStyle.AddAttributesToRender(writer, this);
				writer.AddAttribute(HtmlTextWriterAttribute.Valign, "top");
				writer.RenderBeginTag(HtmlTextWriterTag.Td); // <td>

				Image img = new Image();
				img.AlternateText = this.HeaderText;
				img.ImageUrl = base.ResolveClientUrl(url);
				img.RenderControl(writer);

				writer.RenderEndTag(); // </td>
			}

			//====================================================================================
			// Content
			//====================================================================================
			writer.AddAttribute(HtmlTextWriterAttribute.Valign, "top");
			writer.AddAttribute(HtmlTextWriterAttribute.Width, this.ControlStyle.Width.ToString());
			writer.RenderBeginTag(HtmlTextWriterTag.Td); // <td>

			// Header
			string header = this.HeaderText;
			if (!String.IsNullOrEmpty(header))
			{
				this.HeaderStyle.AddAttributesToRender(writer);
				writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span>
				writer.Write(header);
				writer.RenderEndTag(); // </span>
				writer.WriteBreak(); // <br/>
			}
			// Text
			foreach (string text in _content)
			{
				writer.Write(text);
				writer.WriteBreak();
			}

			// If in design mode we will need to provide some text.
			if (this.DesignMode && _content.Count == 0)
			{
				writer.Write("[ WebTools.UI.WebControls.Alert ] - {0}", this.ID);
			}
			writer.RenderEndTag(); // </td>

			writer.RenderEndTag(); // </tr>
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Renders the control for designer support.
		/// </summary>
		/// <param name="writer">The HtmlTextWriter to write output to.</param>
		private void RenderDesignContents(HtmlTextWriter writer)
		{
			this.RenderBeginTag(writer);
			this.RenderContents(writer);
			this.RenderEndTag(writer);
		}

		/// <summary>
		/// Gets a value indicating whether or not the control contains text content.
		/// </summary>
		/// <returns>A value indicating whether or not the control contains text content.</returns>
		private bool ContainsContent()
		{
			// Text
			if (!String.IsNullOrEmpty(this.Text))
			{
				_content.Add(this.Text);
			}

			// Error Messages
			if (this.AlertType == AlertType.Error)
			{
				string[] errorMessages = this.GetErrorMessages();
				if (errorMessages != null && errorMessages.Length > 0)
				{
					foreach (string msg in errorMessages)
					{
						_content.Add(msg);
					}
				}
			}

			return (_content.Count > 0);
		}

		/// <summary>
		/// Gets any error messages from validation controls for the current validation group.
		/// </summary>
		/// <returns>An array of error messages from validation controls.</returns>
		private string[] GetErrorMessages()
		{
			string[] messages = null;
			ValidatorCollection validators = this.Page.GetValidators(this.ValidationGroup);
			int errorCount = 0;
			for (int i = 0; i < validators.Count; i++)
			{
				IValidator validator = validators[i];
				if (!validator.IsValid)
				{
					if (!String.IsNullOrEmpty(validator.ErrorMessage))
					{
						errorCount++;
					}
				}
			}
			if (errorCount > 0)
			{
				messages = new string[errorCount];
				int index = 0;
				for (int i = 0; i < validators.Count; i++)
				{
					IValidator val = validators[i];
					if ((!val.IsValid) && (!String.IsNullOrEmpty(val.ErrorMessage)))
					{
						messages[index] = String.Copy(val.ErrorMessage);
						index++;
					}
				}
			}
			return messages;
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets the Html tag key for the current control.
		/// </summary>
		/// <value>One of the <seealso cref="System.Web.UI.HtmlTextWriterTag"/> values.</value>
		protected override HtmlTextWriterTag TagKey
		{
			get { return HtmlTextWriterTag.Table; }
		}

		/// <summary>
		/// Gets or sets the validation group the current control will render messages for.
		/// </summary>
		/// <value>The string value of the validation group for which the Alert control will display error messages.</value>
		[Bindable(true)]
		[Category("Validation")]
		[DefaultValue((string)null)]
		[Description("Sets the validation group used to render error messages.")]
		public string ValidationGroup
		{
			get
			{
				object obj = ViewState["ValidationGroup"];
				if (obj != null)
				{
					return (string)obj;
				}
				return String.Empty;
			}
			set { ViewState["ValidationGroup"] = value; }
		}

		/// <summary>
		/// Gets or sets the text to display as the header for alert messages.
		/// </summary>
		/// <value>A string value that will be displayed above the success or error messages when rendered.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue((string)null)]
		[Description("Sets the header text to display with the message.")]
		public string HeaderText
		{
			get
			{
				object obj = ViewState["HeaderText"];
				if (obj != null)
				{
					return (string)obj;
				}
				return String.Empty;
			}
			set { ViewState["HeaderText"] = value; }
		}

		/// <summary>
		/// Gets or sets the text to display in the rendered alert control.
		/// </summary>
		/// <value>A string value of the text content of the rendered control. Will use the <seealso cref="AlertType"/> 
		/// value when rendering to render the proper control styles.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue((string)null)]
		[Description("Sets the text of the message. The default AlertType will be used when rendering.")]
		public string Text
		{
			get { return _text; }
			set { _text = value; }
		}

		/// <summary>
		/// Gets or sets the error text to be rendered by the alert control. This is the same as setting the 
		/// <seealso cref="AlertType"/> property to Error and setting the Text property.
		/// </summary>
		/// <value>A string value specific to an error message.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue((string)null)]
		[Description("Sets the text of the error message.")]
		public string ErrorText
		{
			get { return this.Text; }
			set
			{
				_alertType = AlertType.Error;
				this.Text = value;
			}
		}

		/// <summary>
		/// Gets or sets the success text to be rendered by the alert control. This is the same as setting the 
		/// <seealso cref="AlertType"/> property to Success and setting the Text property.
		/// </summary>
		/// <value>A string value specific to a success message.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue((string)null)]
		[Description("Sets the text of the success message.")]
		public string SuccessText
		{
			get { return this.Text; }
			set
			{
				_alertType = AlertType.Success;
				this.Text = value;
			}
		}

		/// <summary>
		/// Gets or sets the type of alert to render.
		/// </summary>
		/// <value>An <seealso cref="WebTools.UI.WebControls.AlertType"/> value used to determine which styles 
		/// to render and whether or not validation controls are validated and the validation messages displayed.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("Error")]
		[Description("Sets the AlertType of the message.")]
		public AlertType AlertType
		{
			get { return _alertType; }
			set { _alertType = value; }
		}

		/// <summary>
		/// Gets or sets the Url of the image to render for error messages.
		/// </summary>
		/// <value>A string value representing the path to the error image.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue((string)null)]
		[Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
		[UrlProperty]
		[Description("Sets the Url of the image icon to display for the error message.")]
		public string ErrorImageUrl
		{
			get
			{
				object obj = ViewState["ErrorImageUrl"];
				if (obj != null)
				{
					return (string)obj;
				}
				return String.Empty;
			}
			set { ViewState["ErrorImageUrl"] = value; }
		}

		/// <summary>
		/// Gets or sets the Url of the image to render for success messages.
		/// </summary>
		/// <value>A string value representing the path to the success image.</value>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue((string)null)]
		[Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
		[UrlProperty]
		[Description("Sets the Url of the image icon to display for the success message.")]
		public string SuccessImageUrl
		{
			get
			{
				object obj = ViewState["SuccessImageUrl"];
				if (obj != null)
				{
					return (string)obj;
				}
				return String.Empty;
			}
			set { ViewState["SuccessImageUrl"] = value; }
		}

		/// <summary>
		/// Gets the styles to be rendered for error messages.
		/// </summary>
		/// <value>An <seealso cref="WebTools.UI.WebControls.AlertStyle"/> class containing the style 
		/// attributes that are rendered to the HTML tag.</value>
		[Bindable(true)]
		[Category("Style")]
		[DefaultValue((string)null)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[Description("The style applied to the error text.")]
		public virtual AlertStyle ErrorStyle
		{
			get
			{
				if (_errorStyle == null)
				{
					_errorStyle = new AlertStyle();
					if (base.IsTrackingViewState)
					{
						((IStateManager)_errorStyle).TrackViewState();
					}
				}
				return _errorStyle;
			}
		}

		/// <summary>
		/// Gets the styles to be rendered for success messages.
		/// </summary>
		/// <value>An <seealso cref="WebTools.UI.WebControls.AlertStyle"/> class containing the style 
		/// attributes that are rendered to the HTML tag.</value>
		[Bindable(true)]
		[Category("Style")]
		[DefaultValue((string)null)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[Description("The style applied to the success text.")]
		public virtual AlertStyle SuccessStyle
		{
			get
			{
				if (_successStyle == null)
				{
					_successStyle = new AlertStyle();
					if (base.IsTrackingViewState)
					{
						((IStateManager)_successStyle).TrackViewState();
					}
				}
				return _successStyle;
			}
		}

		/// <summary>
		/// Gets the styles to be rendered for panel that will contain the alert image.
		/// </summary>
		/// <value>An <seealso cref="WebTools.UI.WebControls.AlertStyle"/> class containing the style 
		/// attributes that are rendered to the HTML tag.</value>
		[Bindable(true)]
		[Category("Style")]
		[DefaultValue((string)null)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[Description("The style applied to the panel rendered around the alert image.")]
		public virtual AlertStyle ImagePanelStyle
		{
			get
			{
				if (_imagePanelStyle == null)
				{
					_imagePanelStyle = new AlertStyle();
					if (base.IsTrackingViewState)
					{
						((IStateManager)_imagePanelStyle).TrackViewState();
					}
				}
				return _imagePanelStyle;
			}
		}

		/// <summary>
		/// Gets the style applied to the header text area of the alert control.
		/// </summary>
		/// <value>An <seealso cref="WebTools.UI.WebControls.AlertStyle"/> class containing the style 
		/// attributes that are rendered to the HTML tag.</value>
		[Bindable(true)]
		[Category("Style")]
		[DefaultValue((string)null)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[Description("The style applied to the header text area of the alert control.")]
		public virtual AlertStyle HeaderStyle
		{
			get
			{
				if (_headerStyle == null)
				{
					_headerStyle = new AlertStyle();
					if (base.IsTrackingViewState)
					{
						((IStateManager)_headerStyle).TrackViewState();
					}
				}
				return _headerStyle;
			}
		}

		///// <summary>
		///// 
		///// </summary>
		//[Bindable(true)]
		//[Category("Appearance")]
		//[DefaultValue((string)null)]
		//[Description("Sets a value indicating whether or not to display the embedded default error image.")]
		//public virtual bool EnableDefaultErrorImage
		//{
		//    get
		//    {
		//        object obj = ViewState["EnableDefaultErrorImage"];
		//        if (obj != null)
		//        {
		//            return (bool)obj;
		//        }
		//        return false;
		//    }
		//    set { ViewState["EnableDefaultErrorImage"] = value; }
		//}

		///// <summary>
		///// 
		///// </summary>
		//[Bindable(true)]
		//[Category("Appearance")]
		//[DefaultValue((string)null)]
		//[Description("Sets the text of the success message.")]
		//public virtual bool EnableDefaultSuccessImage
		//{
		//    get
		//    {
		//        object obj = ViewState["EnableDefaultSuccessImage"];
		//        if (obj != null)
		//        {
		//            return (bool)obj;
		//        }
		//        return false;
		//    }
		//    set { ViewState["EnableDefaultSuccessImage"] = value; }
		//}
		#endregion
	}
}
